#include "StdAfx.h"
#include "ManagedDebug.h"

using namespace System;

namespace Adaptive
{
	namespace Win32
	{
		namespace Debugging
		{
			// <summary>
			// Static constructor.
			// </summary>
			static ManagedDebug::ManagedDebug()
			{
			}
			// <summary>
			// Enables a debugger to continue a thread that previously reported a debugging event.
			// </summary>
			// <param name="processId">
			// A handle to the process to continue.
			// </param>
			// <param name="threadId">
			// A handle to the thread to continue. The combination of process identifier and thread 
			// identifier must identify a thread that has previously reported a debugging event.
			// </param>
			// <param name="continueStatus">
			// The options to continue the thread that reported the debugging event.
			// </param>
			// <returns>
			// If the function succeeds, the return value is <b>true</b>; otherwise,
			// returns <b>false</b>.
			// </returns>
			bool ManagedDebug::ContinueDebug(int processId, int threadId, ContinueStatus continueStatus)
			{
				return ContinueDebug(gcnew IntPtr(processId), gcnew IntPtr(threadId), continueStatus);
			}
			// <summary>
			// Enables a debugger to continue a thread that previously reported a debugging event.
			// </summary>
			// <param name="processId">
			// A handle to the process to continue.
			// </param>
			// <param name="threadId">
			// A handle to the thread to continue. The combination of process identifier and thread identifier must identify a thread that has previously reported a debugging event.
			// </param>
			// <param name="continueStatus">
			// The options to continue the thread that reported the debugging event.
			// </param>
			// <returns>
			// If the function succeeds, the return value is <b>true</b>; otherwise,
			// returns <b>false</b>.
			// </returns>
			bool ManagedDebug::ContinueDebug(IntPtr^ processId, IntPtr^ threadId, ContinueStatus continueStatus)
			{
				bool returnValue = false;       //Return value.

				try
				{
					returnValue = (ContinueDebugEvent((DWORD)processId->ToInt32(), (DWORD)threadId->ToInt32(), (DWORD)continueStatus) != 0);
				}
				catch(...)
				{
					returnValue = false;
				}
				return returnValue;
			}
			// <summary>
			// Enables a debugger to attach to an active process and debug it.
			// </summary>
			// <param name="processId">
			// The identifier for the process to be debugged. 
			// </param>
			// <returns>
			// If the function succeeds, the return value is <b>true</b>; otherwise,
			// returns <b>false</b>.
			// </returns>
			bool ManagedDebug::DebugActiveProcess(int processId)
			{
				return DebugActiveProcess(gcnew IntPtr(processId));
			}
			// <summary>
			// Enables a debugger to attach to an active process and debug it.
			// </summary>
			// <param name="processId">
			// The identifier for the process to be debugged. 
			// </param>
			// <returns>
			// If the function succeeds, the return value is <b>true</b>; otherwise,
			// returns <b>false</b>.
			// </returns>
			bool ManagedDebug::DebugActiveProcess(IntPtr^ processId)
			{
				bool returnValue = false;               //Return value.

				try
				{
					returnValue = DebugActiveProcess((DWORD)processId->ToInt32());
				}
				catch(...)
				{
					returnValue = false;
				}
				return returnValue;
			}
			// <summary>
			// Stops the debugger from debugging the specified process.
			// </summary>
			// <param name="processId">
			// The identifier for the process to be debugged. 
			// </param>
			// <returns>
			// If the function succeeds, the return value is <b>true</b>; otherwise,
			// returns <b>false</b>.
			// </returns>
			bool ManagedDebug::DebugActiveProcessStop(IntPtr^ processId)
			{
				bool returnValue = false;

				try
				{
					returnValue = (::DebugActiveProcessStop((DWORD)(processId->ToInt32())) != 0);
				}
				catch(...)
				{
					returnValue = false;
				}
				return returnValue;
			}
			// <summary>
			// Causes a breakpoint exception to occur in the current process. 
			// This allows the calling thread to signal the debugger to handle 
			// the exception.
			// </summary>
			void ManagedDebug::BreakDebug()
			{
				try
				{
					DebugBreak();
				}
				catch(...)
				{
				}
			}
			// <summary>
			// Causes a breakpoint exception to occur in the specified process. This 
			// allows the calling thread to signal the debugger to handle the 
			// exception.
			// </summary>
			// <param name="processId">
			// A handle to the process.
			// </param>
			// <returns>
			// If the function succeeds, the return value is <b>true</b>; otherwise,
			// returns zero.
			// </returns>
			bool ManagedDebug::DebugBreakProcess(IntPtr^ processId)
			{
				bool returnValue = false;

				try
				{
					returnValue = (::DebugBreakProcess((HANDLE)(processId->ToInt32())) != 0);
				}
				catch(...)
				{
					returnValue = false;
				}
				return returnValue;
			}
			// <summary>
			// Sets the action to be performed when the debugging thread exits.
			// </summary>
			// <param name="killOnExit">
			// If this parameter is <b>true</b>, the debug thread will kill the 
			// process being debugged on exit. Otherwise, the debug thread will 
			// detach from the process being debugged on exit. 
			// </param>
			// <returns>
			// If the function succeeds, the return value is <b>true</b>.
			// </returns>
			bool ManagedDebug::DebugSetProcessKillOnExit(bool killOnExit)
			{
				bool returnValue = false;

				try
				{
					returnValue = (::DebugSetProcessKillOnExit(killOnExit) != 0);
				}
				catch(...)
				{
					returnValue = false;
				}
				return returnValue;
			}
			// <summary>
			// Transfers execution control to the debugger. The behavior of the 
			// debugger thereafter is specific to the type of debugger used.
			// </summary>
			// <param name="exitCode">
			// The error code associated with the exit.
			// </param>
			void ManagedDebug::FatalExit(int exitCode)
			{
				try
				{
					::FatalExit(exitCode);
				}
				catch(...)
				{
				}
			}
			// <summary>
			// Flushes the instruction cache for the specified process.
			// </summary>
			// <param name="processHandle">
			// A handle to a process whose instruction cache is to be flushed.
			// </param>
			// <param name="baseAddressPointer">
			// A pointer to the base of the region to be flushed. This parameter can be <b>null</b>. 
			// </param>
			// <param name="size">
			// The size of the region to be flushed if the lpBaseAddress parameter is not NULL, in bytes.
			// </param>
			// <returns>
			// If the function succeeds, the return value is <b>true</b>.
			// </returns>
			bool ManagedDebug::FlushInstructionCache(IntPtr^ processHandle, int^ baseAddressPointer, int size)
			{
				bool returnValue = false;

				try
				{
					returnValue = (::FlushInstructionCache((HANDLE)*processHandle, (LPCVOID)&baseAddressPointer, size) != 0);
				}
				catch(...)
				{
					returnValue = false;
				}
				return returnValue;
			}
			// <summary>
			// Determines whether the calling process is being debugged by a user-mode debugger.
			// </summary>
			// <returns>
			// The current process is running in the context of a debugger, the return value is <b>true</b>; 
			// otherwise, the value is <b>false</b>.
			// </returns>
			bool ManagedDebug::IsDebuggerPresent()
			{
				bool returnValue = false;

				try
				{
					returnValue = (::IsDebuggerPresent() != 0);
				}
				catch(...)
				{
					returnValue = false;
				}
				return returnValue;
			}
			// <summary>
			// Sends a string to the debugger for display.
			// </summary>
			// <param name="outputString">
			// The null-terminated string to be displayed.
			// </param>
			void ManagedDebug::OutputDebugString(String^ outputString)
			{
				try
				{
					::OutputDebugString(((CString)outputString));
				}
				catch(...)
				{
				}
			}
		}
	}
}